package com.sfl.api_backend.controller.task;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sfl.api_backend.constant.HttpCode;
import com.sfl.api_backend.entity.Datasets;
import com.sfl.api_backend.entity.Imgs;
import com.sfl.api_backend.entity.Task;
import com.sfl.api_backend.service.IDatasetsService;
import com.sfl.api_backend.service.IImgsService;
import com.sfl.api_backend.service.ITaskService;
import com.sfl.api_backend.utils.Api.RestResult;
import com.sfl.api_backend.utils.RandomID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 任务表 前端控制器
 * </p>
 *
 * @author szc
 * @since 2023-01-27
 */
@RestController
@RequestMapping("/pred")
@Slf4j
public class TaskController {

    @Resource
    private ITaskService taskService;

    @Value("${file.upload.path}")
    private String uploadPath;

    @Resource
    private IDatasetsService datasetsService;

    @Resource
    private IImgsService imgsService;

    @PostMapping("/task/makeTask")
    @PreAuthorize("hasAuthority('User')")
    public RestResult makeTask(@RequestBody Task task){
        try{
            log.info("make task: {}", task);
            task.setTaskId(RandomID.getRandomID());
            LocalDateTime now = LocalDateTime.now();
            task.setCreateTime(now);
            task.setLastRunTime(now);
            task.setLabelSetId(RandomID.getRandomID());

            taskService.save(task);
            return RestResult.success();
        }
        catch (Exception e){
            log.error("make task error: {}", task);
            return RestResult.error(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @PostMapping("/task/modify")
    @PreAuthorize("hasAuthority('User')")
    public RestResult modifyTask(@RequestBody Task task){
        try{
            log.info("modify task: {}", task);
            taskService.updateById(task);
            return RestResult.success();
        }
        catch (Exception e){
            log.error("modify task error: {}", task);
            return RestResult.error(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @PostMapping("/task/list")
    @PreAuthorize("hasAuthority('User')")
    public RestResult listTask(@RequestBody Task vo)
    {
        try{
            log.info("list task: {}", vo.getUserId());
            Wrapper<Task> wrapper = new LambdaQueryWrapper<Task>().eq(Task::getUserId, vo.getUserId());
            return RestResult.success(taskService.list(wrapper));
        }
        catch (Exception e){
            log.error("list task error: {}", vo.getUserId());
            return RestResult.error(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @PostMapping("/task/imgsList")
    @PreAuthorize("hasAuthority('User')")
    public RestResult imgsList(@RequestBody Task vo)
    {
        try{
            log.info("imgs list task: {}", vo.getTaskId());
            return taskService.TaskImgsList(vo);
        }
        catch (Exception e){
            log.error("imgs list error: {}", vo.getTaskId());
            return RestResult.error(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    @PostMapping("/task/about")
    @PreAuthorize("hasAuthority('User')")
    public RestResult aboutTask(@RequestBody Task vo)
    {
        try{
            log.info("about task: {}", vo.getUserId());
            return taskService.aboutTask(vo);
        }
        catch (Exception e){
            log.error("about task error: {}", vo.getUserId());
            return RestResult.error(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }


    @PostMapping("/task/delete")
    @PreAuthorize("hasAuthority('User')")
    public RestResult deleteTask(@RequestBody List<Integer> task_ids)
    {
        try{
            log.info("delete task: {}", task_ids);
            taskService.removeByIds(task_ids);
            return RestResult.success();
        }
        catch (Exception e){
            log.error("delete task error: {}", task_ids);
            return RestResult.error(HttpCode.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

    /**
     * 推理模块 -- 配合RabbitMQ
     */
    @PostMapping("/task/runTask")
    @PreAuthorize("hasAuthority('User')")
    public RestResult runTask(@RequestBody Task vo)
    {
        log.info("run task: {}", vo);
        return taskService.runTask(vo);
    }


    /**
     *
     */
    @PostMapping("/task/runImg")
    @PreAuthorize("hasAuthority('User')")
    @Async
    public RestResult runImg(@RequestParam("files[]")List<MultipartFile> files, @RequestParam("names[]") List<String> names, @RequestParam("configs[]") List<String> configs) throws Exception
    {
        log.info("run task img: {}", configs.get(0));
        try{
            Imgs imgs = new Imgs();

            // create datasets
            Datasets datasets = new Datasets();
            datasets.setImgsetId(RandomID.getRandomID());
            LocalDateTime now = LocalDateTime.now();
            datasets.setImgsetName("单独推理_" + now);
            datasets.setUserId(Integer.valueOf(configs.get(0)));
            datasets.setImgsetPath(uploadPath + configs.get(0) + "/datasets/"+datasets.getImgsetId()+"/");
            datasets.setRepresent("单独推理_" + now);
            datasets.setCreateTime(now);
            File file = new File(datasets.getImgsetPath());

            if (!file.exists()) {
                file.mkdirs();
            }

            log.info("make imgsets: {}",datasets.getImgsetId());

            // create img
            for (int i=0;i < files.size();i++){
                MultipartFile multipartFile = files.get(i);
                String name = names.get(i);
                System.out.println(name);

                if(!multipartFile.isEmpty()){
                    String path = uploadPath + configs.get(0) + "/datasets/" + datasets.getImgsetId() + "/";
                    if(files.size() > 1){
                        name = name.substring(name.indexOf("/"));
                    }
                    System.out.println(path+name);
                    File fileToSave = new File(path,name);

                    try(OutputStream outputStream = new FileOutputStream(fileToSave)){
                        outputStream.write(multipartFile.getBytes());
                        imgs.setImgId(RandomID.getRandomID());
                        imgs.setImgName(name);
                        imgs.setUserId(datasets.getUserId());
                        imgs.setImgPath(path+name);
                        imgs.setImgsetId(datasets.getImgsetId());
                        imgs.setCreateTime(LocalDateTime.now());

                        log.info("make img: {}",imgs.getImgId());
                    }
                }
            }

            // create task
            Task task = new Task();
            task.setTaskId(RandomID.getRandomID());
            task.setTaskName("单独推理_" + now);
            task.setUserId(Integer.valueOf(configs.get(0)));
            task.setExScriptId(Integer.valueOf(configs.get(1)));
            task.setBackScriptId(Integer.valueOf(configs.get(2)));
            task.setImgsetId(datasets.getImgsetId());
            task.setModelId(Integer.valueOf(configs.get(3)));
            task.setCreateTime(LocalDateTime.now());
            task.setLastRunTime(LocalDateTime.now());
            log.info("make task: {}",task.getTaskId());

            datasetsService.save(datasets);
            imgsService.save(imgs);
            taskService.save(task);

            taskService.runTask(task);
            log.info("run task: {}",task.getTaskId());

            return RestResult.success();
        }
        catch (RuntimeException e){
            log.error("run task img: {} erro", configs.get(0));
            return RestResult.error(HttpCode.NOT_IMPLEMENTED, e.getMessage());
        }
    }

}
